<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>线程池监控中心</title>
    <!-- 1. 引入Vue3 CDN -->
    <script src="https://unpkg.com/vue@3.3.4/dist/vue.global.prod.js"></script>
    <!-- 2. 引入Element Plus CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-plus@2.4.2/dist/index.css">
    <!-- 3. 引入Element Plus JS -->
    <script src="https://unpkg.com/element-plus@2.4.2/dist/index.full.js"></script>
    <!-- 4. 引入Element Plus Icons（图标） -->
    <script src="https://unpkg.com/@element-plus/icons-vue@2.1.0/dist/index.iife.min.js"></script>
    <!-- 5. 引入ECharts（趋势图） -->
    <script src="https://unpkg.com/echarts@5.4.3/dist/echarts.min.js"></script>
    <!-- 6. 引入Axios（接口请求） -->
    <script src="https://unpkg.com/axios@1.5.1/dist/axios.min.js"></script>
    <!-- 7. 自定义样式 -->
    <style>
        .threadpool-monitor-container {
            padding: 20px;
            font-family: "Microsoft YaHei", sans-serif;
        }

        .card-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 16px;
        }

        .chart-container {
            width: 100%;
            height: 400px;
            margin-top: 20px;
        }

        .el-progress {
            width: 120px;
        }

        .el-table {
            margin-bottom: 16px;
        }

        .el-dialog__body {
            max-height: 60vh;
            overflow-y: auto;
        }
    </style>
</head>
<body>
<div id="app" class="threadpool-monitor-container">
    <!-- 页面标题 -->
    <el-page-header content="线程池监控中心"></el-page-header>

    <!-- 1. 线程池状态概览 -->
    <el-card shadow="hover" class="mt-4">
        <div class="card-header">
            <span>线程池状态概览</span>
            <el-button type="primary" size="small" @click="refreshStats">
                <el-icon>
                    <Refresh/>
                </el-icon>
                刷新
            </el-button>
        </div>

        <el-table
                :data="poolStatsList"
                border
                stripe
                :loading="tableLoading"
                style="width: 100%"
        >
            <el-table-column label="线程池名称" prop="poolName" align="center" width="180"></el-table-column>
            <el-table-column label="核心线程数" prop="corePoolSize" align="center"></el-table-column>
            <el-table-column label="最大线程数" prop="maximumPoolSize" align="center"></el-table-column>
            <el-table-column label="活跃线程数" prop="activeThreads" align="center"></el-table-column>
            <el-table-column label="空闲线程数" prop="idleThreads" align="center"></el-table-column>
            <el-table-column label="队列容量" align="center">
                <template #default="scope">
                    {{ scope.row.queueSize }}/{{ scope.row.queueCapacity }}
                </template>
            </el-table-column>
            <el-table-column label="队列使用率" prop="queueUsageRatio" align="center">
                <template #default="scope">
                    <el-progress :percentage="scope.row.queueUsageRatio" :format="formatPercent" size="small"/>
                </template>
            </el-table-column>
            <el-table-column label="任务完成率" prop="taskCompletionRatio" align="center">
                <template #default="scope">
                    <el-progress :percentage="scope.row.taskCompletionRatio" :format="formatPercent" size="small"/>
                </template>
            </el-table-column>
            <el-table-column label="拒绝任务数" prop="rejectedCount" align="center"></el-table-column>
            <el-table-column label="平均执行时间(ms)" prop="avgTaskExecuteTime" align="center">
                <template #default="scope">
                    {{ scope.row.avgTaskExecuteTime.toFixed(1) }}
                </template>
            </el-table-column>
            <el-table-column label="操作" align="center" width="220">
                <template #default="scope">
                    <el-button type="primary" size="small" @click="openConfigDialog(scope.row)">
                        <el-icon>
                            <Edit/>
                        </el-icon>
                        手动配置
                    </el-button>
                    <el-button type="success" size="small" @click="viewTrend(scope.row.poolName)">
                        <el-icon>
                            <Chart/>
                        </el-icon>
                        趋势分析
                    </el-button>
                </template>
            </el-table-column>
        </el-table>
    </el-card>

    <!-- 2. 趋势分析区域 -->
    <el-card shadow="hover" class="mt-4" v-if="showTrend">
        <div class="card-header">
            <span>{{ currentPoolName }} - 趋势分析</span>
            <el-select
                    v-model="trendType"
                    placeholder="选择趋势指标"
                    size="small"
                    @change="refreshTrend"
                    class="ml-4"
                    style="width: 200px"
            >
                <el-option label="活跃线程比例(%)" value="avgActiveThreadRatio"></el-option>
                <el-option label="队列使用率(%)" value="queueUsageRatio"></el-option>
                <el-option label="任务完成率(%)" value="taskCompletionRatio"></el-option>
                <el-option label="平均执行时间(ms)" value="avgTaskExecuteTime"></el-option>
            </el-select>
        </div>
        <!-- ECharts趋势图容器 -->
        <div class="chart-container" id="trendChart"></div>
    </el-card>

    <!-- 3. 策略配置区域 -->
    <el-card shadow="hover" class="mt-4">
        <div class="card-header">
            <span>动态调整策略</span>
            <el-button type="primary" size="small" @click="openStrategyDialog(null)">
                <el-icon>
                    <Plus/>
                </el-icon>
                新增策略
            </el-button>
        </div>

        <el-table
                :data="strategyList"
                border
                stripe
                style="width: 100%"
        >

            <el-table-column label="策略名称" prop="strategyName" align="center" width="180"></el-table-column>
            <el-table-column label="关联线程池" prop="poolName" align="center">
                <template #default="scope">
                    {{ scope.row.poolName || '全局策略' }}
                </template>
            </el-table-column>
            <el-table-column label="触发条件" prop="triggerCondition" align="center" width="300"></el-table-column>
            <el-table-column label="调整动作" prop="adjustAction" align="center" width="300"></el-table-column>
            <el-table-column label="状态" prop="status" align="center">
                <template #default="scope">
                    <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
                        {{ scope.row.status === 1 ? '启用' : '禁用' }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column label="操作" align="center" width="180">
                <template #default="scope">
                    <el-button type="primary" size="small" @click="openStrategyDialog(scope.row)">
                        <el-icon>
                            <Edit/>
                        </el-icon>
                        编辑
                    </el-button>
                    <el-button type="danger" size="small" @click="deleteStrategy(scope.row.strategyId)">
                        <el-icon>
                            <Delete/>
                        </el-icon>
                        删除
                    </el-button>
                </template>
            </el-table-column>
        </el-table>
    </el-card>

    <!-- 4. 手动配置弹窗 -->
    <el-dialog
            title="手动配置线程池参数"
            v-model="configDialogVisible"
            width="500px"
            :before-close="handleConfigDialogClose"
    >
        <el-form
                :model="configForm"
                ref="configFormRef"
                label-width="120px"
                :rules="configFormRules"
        >
            <el-form-item label="线程池名称" prop="poolName">
                <el-input v-model="configForm.poolName" disabled/>
            </el-form-item>
            <el-form-item label="核心线程数" prop="corePoolSize">
                <el-input v-model.number="configForm.corePoolSize"/>
            </el-form-item>
            <el-form-item label="最大线程数" prop="maximumPoolSize">
                <el-input v-model.number="configForm.maximumPoolSize"/>
            </el-form-item>
            <el-form-item label="队列容量" prop="queueCapacity">
                <el-input v-model.number="configForm.queueCapacity"/>
                <div class="el-form-item__error">仅支持ArrayBlockingQueue类型队列调整</div>
            </el-form-item>
        </el-form>
        <template #footer>
            <el-button @click="()=>{configDialogVisible.value=false}">取消</el-button>
            <el-button type="primary" @click="submitConfig">确认配置</el-button>
        </template>
    </el-dialog>

    <!-- 5. 策略配置弹窗 -->
    <el-dialog
            title="策略配置"
            v-model="strategyDialogVisible"
            width="800px"
            :before-close="handleStrategyDialogClose"
    >
        <span>activeThreadRatio：活跃线程比例（%），queueUsageRatio：队列使用率（%）</span>
        <el-form
                :model="strategyForm"
                ref="strategyFormRef"
                label-width="150px"
                :rules="strategyFormRules"
        >
            <el-form-item label="策略名称" prop="strategyName">
                <el-input v-model="strategyForm.strategyName"/>
            </el-form-item>
            <el-form-item label="关联线程池" prop="poolName">
                <el-select v-model="strategyForm.poolName" placeholder="选择线程池（空为全局）">
                    <el-option label="全局策略" value=""/>
                    <el-option
                            v-for="pool in poolStatsList"
                            :key="pool.poolName"
                            :label="pool.poolName"
                            :value="pool.poolName"
                    />
                </el-select>
            </el-form-item>
            <el-form-item label="触发条件(SpEL)" prop="triggerCondition">
                <el-input
                        v-model="strategyForm.triggerCondition"
                        placeholder="示例：activeThreadRatio>90 && queueUsageRatio>70"
                />
                <div class="el-form-item__error">
                    支持变量：activeThreadRatio/queueUsageRatio/taskCompletionRatio/rejectedCount/idleThreads
                </div>
            </el-form-item>
            <el-form-item label="触发次数阈值" prop="triggerDuration">
                <el-input
                        v-model.number="strategyForm.triggerDuration"
                        placeholder="连续满足条件N次后执行调整"
                />
            </el-form-item>
            <el-form-item label="调整动作(JSON)" prop="adjustAction">
                <el-input
                        v-model="strategyForm.adjustAction"
                        placeholder='示例：{"corePoolSize":"+5","maximumPoolSize":"*1.5","queueCapacity":"+200"}'
                />
            </el-form-item>
            <el-form-item label="恢复条件(SpEL)" prop="recoverCondition">
                <el-input
                        v-model="strategyForm.recoverCondition"
                        placeholder="示例：activeThreadRatio<30 && queueUsageRatio<20"
                />
            </el-form-item>
            <el-form-item label="恢复动作(JSON)" prop="recoverAction">
                <el-input
                        v-model="strategyForm.recoverAction"
                        placeholder='示例：{"corePoolSize":"-5","maximumPoolSize":"/1.5","queueCapacity":"-200"}'
                />
            </el-form-item>
            <el-form-item label="恢复次数阈值" prop="recoverDuration">
                <el-input
                        v-model.number="strategyForm.recoverDuration"
                        placeholder="连续满足条件N次后执行恢复"
                />
            </el-form-item>
            <el-form-item label="策略状态" prop="status">
                <el-select v-model="strategyForm.status">
                    <el-option label="启用" value="1"></el-option>
                    <el-option label="禁用" value="0"></el-option>
                </el-select>
            </el-form-item>
        </el-form>
        <template #footer>
            <el-button @click="handleConfigDialogClose">取消</el-button>
            <el-button type="primary" @click="submitStrategy">保存策略</el-button>
        </template>
    </el-dialog>
</div>

<!-- Vue3逻辑代码 -->
<script>
    // 1. 初始化Vue应用
    const {createApp, ref, reactive, onMounted, nextTick, getCurrentInstance} = Vue;
    const app = createApp({
        setup() {
            // ---------------------- 1. 响应式数据定义 ----------------------
            // 线程池状态列表
            const poolStatsList = ref([]);
            // 策略列表
            const strategyList = ref([]);
            // 表格加载状态
            const tableLoading = ref(false);
            // 趋势分析显示状态
            const showTrend = ref(false);
            // 当前趋势分析的线程池名称
            const currentPoolName = ref('');
            // 趋势指标类型（默认活跃线程比例）
            const trendType = ref('avgActiveThreadRatio');
            // ECharts实例
            const trendChartInstance = ref(null);

            // 手动配置弹窗相关
            const configDialogVisible = ref(false);
            const configFormRef = ref(null);
            const configForm = reactive({
                poolName: '',
                corePoolSize: 0,
                maximumPoolSize: 0,
                queueCapacity: 0
            });
            // 手动配置表单验证规则
            const configFormRules = reactive({
                corePoolSize: [
                    {required: true, message: '请输入核心线程数', trigger: 'blur'},
                    {type: 'number', min: 0, message: '核心线程数不能小于0', trigger: 'blur'}
                ],
                maximumPoolSize: [
                    {required: true, message: '请输入最大线程数', trigger: 'blur'},
                    {type: 'number', min: 1, message: '最大线程数不能小于1', trigger: 'blur'}
                ],
                queueCapacity: [
                    {required: true, message: '请输入队列容量', trigger: 'blur'},
                    {type: 'number', min: 1, message: '队列容量不能小于1', trigger: 'blur'}
                ]
            });

            // 策略配置弹窗相关
            const strategyDialogVisible = ref(false);
            const strategyFormRef = ref(null);
            const strategyForm = reactive({
                strategyId: '',
                strategyName: '',
                poolName: '',
                triggerCondition: '',
                triggerDuration: 3,
                adjustAction: '',
                recoverCondition: '',
                recoverDuration: 5,
                status: 1 // 1-启用，0-禁用
            });
            // 策略表单验证规则
            const strategyFormRules = reactive({
                strategyName: [
                    {required: true, message: '请输入策略名称', trigger: 'blur'}
                ],
                triggerCondition: [
                    {required: true, message: '请输入触发条件', trigger: 'blur'}
                ],
                triggerDuration: [
                    {required: true, message: '请输入触发次数阈值', trigger: 'blur'},
                    {type: 'number', min: 1, message: '阈值不能小于1', trigger: 'blur'}
                ],
                adjustAction: [
                    {required: true, message: '请输入调整动作', trigger: 'blur'}
                ],
                recoverCondition: [
                    {required: true, message: '请输入恢复条件', trigger: 'blur'}
                ],
                recoverDuration: [
                    {required: true, message: '请输入恢复次数阈值', trigger: 'blur'},
                    {type: 'number', min: 1, message: '阈值不能小于1', trigger: 'blur'}
                ],
                status: [
                    {required: true, message: '请选择策略状态', trigger: 'change'}
                ]
            });

            // ---------------------- 2. 接口请求封装 ----------------------
            // 后端API基础路径（需根据实际部署地址修改）
            const API_BASE_URL = window.location.href.replace('/threadpool-monitor.html', '/api'); // 本地后端地址
            // 线程池监控API
            const threadpoolApi = {
                // 获取所有线程池状态
                getAllStats: () => axios.get(`${API_BASE_URL}/threadpool/all-stats`),
                // 获取指定线程池趋势
                getTrend: (poolName) => axios.get(`${API_BASE_URL}/threadpool/trend/${poolName}`),
                // 手动配置参数
                configParams: (data) => axios.post(`${API_BASE_URL}/threadpool/config`, data),
                // 获取所有策略
                getAllStrategies: () => axios.get(`${API_BASE_URL}/threadpool/strategies`),
                // 保存策略（新增/更新）
                saveStrategy: (data) => axios.post(`${API_BASE_URL}/threadpool/strategy/save`, data),
                // 删除策略
                deleteStrategy: (strategyId) => axios.delete(`${API_BASE_URL}/threadpool/strategy/${strategyId}`)
            };

            // ---------------------- 3. 核心方法定义 ----------------------
            /**
             * 加载所有数据（线程池状态+策略）
             */
            const loadAllData = async () => {
                try {
                    tableLoading.value = true;
                    // 并行请求线程池状态和策略列表
                    const [statsRes, strategyRes] = await Promise.all([
                        threadpoolApi.getAllStats(),
                        threadpoolApi.getAllStrategies()
                    ]);
                    poolStatsList.value = statsRes.data || [];
                    strategyList.value = strategyRes.data || [];
                } catch (e) {
                    ElementPlus.ElMessage.error('数据加载失败：' + (e.response?.data || e.message));
                } finally {
                    tableLoading.value = false;
                }
            };

            /**
             * 刷新线程池状态
             */
            const refreshStats = async () => {
                try {
                    const res = await threadpoolApi.getAllStats();
                    poolStatsList.value = res.data || [];
                    ElementPlus.ElMessage.success('刷新成功');
                } catch (e) {
                    ElementPlus.ElMessage.error('刷新失败：' + (e.response?.data || e.message));
                }
            };

            /**
             * 查看趋势分析
             */
            const viewTrend = async (poolName) => {
                try {
                    currentPoolName.value = poolName;
                    showTrend.value = true;
                    // 等待DOM渲染完成后初始化图表
                    await nextTick();
                    await refreshTrend();
                } catch (e) {
                    ElementPlus.ElMessage.error('趋势分析加载失败：' + (e.response?.data || e.message));
                }
            };

            /**
             * 刷新趋势图表
             */
            const refreshTrend = async () => {
                try {
                    // 1. 请求趋势数据
                    const res = await threadpoolApi.getTrend(currentPoolName.value);
                    const trendData = res.data;
                    if (!trendData) {
                        ElementPlus.ElMessage.warning('无趋势数据');
                        return;
                    }

                    // 2. 初始化ECharts实例
                    if (!trendChartInstance.value) {
                        const chartDom = document.getElementById('trendChart');
                        trendChartInstance.value = echarts.init(chartDom);
                        // 窗口 resize 时图表自适应
                        window.addEventListener('resize', () => {
                            trendChartInstance.value.resize();
                        });
                    }

                    // 3. 构建图表配置
                    const chartOption = {
                        title: {
                            text: `${currentPoolName.value} - ${getTrendLabel(trendType.value)}趋势`,
                            left: 'center'
                        },
                        tooltip: {
                            trigger: 'axis',
                            axisPointer: {type: 'shadow'}
                        },
                        grid: {
                            left: '3%',
                            right: '4%',
                            bottom: '3%',
                            containLabel: true
                        },
                        xAxis: {
                            type: 'category',
                            // 时间轴：按采集频率（10秒/次）生成，如“0s前”“10s前”...
                            data: Array.from({length: trendData.dataCount}, (_, i) => `${i * 10}s前`).reverse()
                        },
                        yAxis: {
                            type: 'value',
                            name: getTrendUnit(trendType.value),
                            nameLocation: 'middle',
                            nameGap: 30
                        },
                        series: [
                            {
                                name: getTrendLabel(trendType.value),
                                type: 'line',
                                data: getTrendSeriesData(trendData), // 生成趋势数据
                                smooth: true, // 平滑曲线
                                itemStyle: {color: '#409EFF'}, // 点颜色
                                lineStyle: {width: 2} // 线宽度
                            }
                        ]
                    };

                    // 4. 渲染图表
                    trendChartInstance.value.setOption(chartOption);
                } catch (e) {
                    ElementPlus.ElMessage.error('图表刷新失败：' + (e.response?.data || e.message));
                }
            };

            /**
             * 获取趋势指标的中文标签
             */
            const getTrendLabel = (type) => {
                const labelMap = {
                    avgActiveThreadRatio: '活跃线程比例',
                    queueUsageRatio: '队列使用率',
                    taskCompletionRatio: '任务完成率',
                    avgTaskExecuteTime: '平均执行时间'
                };
                return labelMap[type] || type;
            };

            /**
             * 获取趋势指标的单位
             */
            const getTrendUnit = (type) => {
                const unitMap = {
                    avgActiveThreadRatio: '%',
                    queueUsageRatio: '%',
                    taskCompletionRatio: '%',
                    avgTaskExecuteTime: 'ms'
                };
                return unitMap[type] || '';
            };

            /**
             * 生成趋势图表的系列数据（模拟波动，实际需后端返回时间序列）
             */
            const getTrendSeriesData = (trendData) => {
                const dataCount = trendData.dataCount;
                const baseValue = trendData[trendType.value];
                // 生成围绕基准值的随机波动数据（模拟真实场景）
                return Array.from({length: dataCount}, () => {
                    const random = Math.random() * 20 - 10; // ±10的波动范围
                    return Math.max(0, baseValue + random); // 确保值非负
                });
            };

            /**
             * 打开手动配置弹窗
             */
            const openConfigDialog = (poolStats) => {
                // 初始化表单数据（从选中的线程池状态获取）
                configForm.poolName = poolStats.poolName;
                configForm.corePoolSize = poolStats.corePoolSize;
                configForm.maximumPoolSize = poolStats.maximumPoolSize;
                configForm.queueCapacity = poolStats.queueCapacity;
                // 显示弹窗
                configDialogVisible.value = true;
            };

            /**
             * 提交手动配置
             */
            const submitConfig = async () => {
                try {
                    // 1. 表单验证
                    const valid = await configFormRef.value.validate();
                    if (!valid) return;

                    // 2. 提交配置到后端
                    const res = await threadpoolApi.configParams(configForm);
                     ElementPlus.ElMessage.success(res.data || '配置成功');
                    // 3. 关闭弹窗并刷新数据
                    configDialogVisible.value = false;
                    refreshStats();
                } catch (e) {
                    // 表单验证失败不提示错误（Element Plus会自动提示）
                    if (e.name !== 'ValidationError') {
                        ElementPlus.ElMessage.error('配置失败：' + (e.response?.data || e.message));
                    }
                }
            };

            /**
             * 打开策略配置弹窗（新增/编辑）
             */
            const openStrategyDialog = (strategy) => {
                // 重置表单验证状态
                if (strategyFormRef.value) {
                    strategyFormRef.value.clearValidate();
                }

                // 初始化表单数据（编辑时赋值，新增时重置）
                if (strategy) {
                    Object.assign(strategyForm, strategy);
                } else {
                    strategyForm.strategyId = '';
                    strategyForm.strategyName = '';
                    strategyForm.poolName = '';
                    strategyForm.triggerCondition = '';
                    strategyForm.triggerDuration = 3;
                    strategyForm.adjustAction = '';
                    strategyForm.recoverCondition = '';
                    strategyForm.recoverDuration = 5;
                    strategyForm.status = 1;
                }

                // 显示弹窗
                strategyDialogVisible.value = true;
            };

            /**
             * 提交策略配置
             */
            const submitStrategy = async () => {
                try {
                    // 1. 表单验证
                    const valid = await strategyFormRef.value.validate();
                    if (!valid) return;

                    // 2. 提交策略到后端
                    const res = await threadpoolApi.saveStrategy(strategyForm);
                     ElementPlus.ElMessage.success(res.data || '策略保存成功');


                    // 3. 关闭弹窗并刷新策略列表
                    strategyDialogVisible.value = false;
                    const strategyRes = await threadpoolApi.getAllStrategies();
                    strategyList.value = strategyRes.data || [];
                } catch (e) {
                    if (e.name !== 'ValidationError') {
                        ElementPlus.ElMessage.error('策略保存失败：' + (e.response?.data || e.message));
                    }
                }
            };

            /**
             * 删除策略
             */
            const deleteStrategy = async (strategyId) => {
                try {
                    // 确认删除
                    await ElMessageBox.confirm(
                        '确定要删除该策略吗？删除后不可恢复！',
                        '确认删除',
                        {
                            confirmButtonText: '确定',
                            cancelButtonText: '取消',
                            type: 'warning'
                        }
                    );

                    // 提交删除请求
                    await threadpoolApi.deleteStrategy(strategyId);
                    ElementPlus.ElMessage.success('策略删除成功');

                    // 刷新策略列表
                    const strategyRes = await threadpoolApi.getAllStrategies();
                    strategyList.value = strategyRes.data || [];
                } catch (e) {
                    // 取消删除不提示
                    if (e.name !== 'Cancel') {
                        ElementPlus.ElMessage.error('策略删除失败：' + (e.response?.data || e.message));
                    }
                }
            };

            /**
             * 格式化百分比显示（保留1位小数）
             */
            const formatPercent = (percentage) => {
                return `${percentage.toFixed(1)}%`;
            };

            /**
             * 关闭手动配置弹窗（重置表单）
             */
            const handleConfigDialogClose = () => {

                if (configFormRef.value) {
                    configFormRef.value.clearValidate();
                }
                configForm.value = {
                    poolName: '',
                    corePoolSize: 0,
                    maximumPoolSize: 0,
                    queueCapacity: 0,
                    keepAliveTime: 0,
                    rejectedHandler: '',
                    threadNamePrefix: '',
                    allowCoreThreadTimeOut: false,
                    threadPoolExecutor: false,
                    queueType: '',
                    queueTimeout: 0,
                    queueTimeoutAction: '',
                    queueTimeoutDuration: 0,
                }
                strategyDialogVisible.value = false;
            };

            /**
             * 关闭策略配置弹窗（重置表单）
             */
            const handleStrategyDialogClose = () => {
                if (strategyFormRef.value) {
                    strategyFormRef.value.clearValidate();
                }
            };

            // ---------------------- 4. 生命周期钩子 ----------------------
            onMounted(() => {
                // 初始化加载数据
                loadAllData();
                // 定时刷新（每10秒，与后端数据采集频率一致）
                setInterval(loadAllData, 10000);
            });

            // ---------------------- 5. 暴露数据和方法到模板 ----------------------
            return {
                poolStatsList,
                strategyList,
                tableLoading,
                showTrend,
                currentPoolName,
                trendType,
                configDialogVisible,
                configFormRef,
                configForm,
                configFormRules,
                strategyDialogVisible,
                strategyFormRef,
                strategyForm,
                strategyFormRules,
                loadAllData,
                refreshStats,
                viewTrend,
                refreshTrend,
                openConfigDialog,
                submitConfig,
                openStrategyDialog,
                submitStrategy,
                deleteStrategy,
                formatPercent,
                handleConfigDialogClose,
                handleStrategyDialogClose
            };
        }
    });

    // 2. 注册Element Plus组件和图标
    app.use(ElementPlus);
    // 注册Element Plus图标（全局可用）
    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
        app.component(key, component);
    }

    // 3. 挂载Vue应用
    app.mount('#app');
</script>
</body>
</html>